package com.steak.mvc;

import lombok.SneakyThrows;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;

/**
 * @author 刘牌
 * @Title:
 * @date 2022-06-2112:33
 */
@Component
public class ApiDoc implements BeanPostProcessor {
    @SneakyThrows
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("apiController")) {
            StringBuilder stringBuilder = new StringBuilder();
            R r = new R();
            Method[] methods = bean.getClass().getMethods();
            for (Method method : methods) {
                String name = method.getName();
                if (name.equals("wait") || name.equals("equals") || name.equals("toString") || name.equals("hashCode") || name.equals("getClass") || name.equals("notify") || name.equals("notifyAll")) {
                } else {
                    /**
                     * 返回类型
                     */
                    Class<?> returnType = method.getReturnType();
                    String typeName = method.getGenericReturnType().getTypeName();
                    System.out.println("type  "+typeName);
                    //如果类型为统一返回类型，那么解析出泛型参数
                    if (returnType == R.class){
                        //如果设置了泛型参数
                        if (typeName.contains("<") && typeName.contains(">")){
                            int start = typeName.indexOf("<") + 1;
                            int end = typeName.indexOf(">");
                            String result = typeName.substring(start, end);
                            Class<?> forName = Class.forName(result);
                            returnType.getMethod("setData", Object.class).invoke(r, forName.newInstance());
                        }else {
                            //returnType.getMethod("setData", Object.class).invoke(r, );
                        }
                    }
                    //其他返回类型，直接返回实例
                    else {
                        System.out.println("0000000  "+returnType.newInstance());
                    }
                    /**
                     *
                     */
                    Class<?>[] classes = method.getParameterTypes();
                    for (Class<?> aClass : classes) {
                        System.out.println("参数类型  "+aClass.getTypeName());
                        Field[] fields = aClass.getDeclaredFields();
                        for (Field field : fields) {
                            System.out.println("字段 "+field.getName());
                        }
                    }

                    Annotation[][] parameterAnnotations = method.getParameterAnnotations();
                    for (Annotation[] annotations : parameterAnnotations) {
                        for (Annotation annotation : annotations) {
                            System.out.println("annotation---" + method.getName() + "--- " + annotation);
                        }
                    }

                    Class<?>[] parameterTypes = method.getParameterTypes();
                    for (Class<?> parameterType : parameterTypes) {
                        System.out.println("parameterType---" + method.getName() + "--- " + parameterType.getName());
                    }

                    Parameter[] parameters = method.getParameters();
                    for (Parameter parameter : parameters) {
                        stringBuilder.append(parameter.getName()+",");
                        System.out.println("parameter---" + method.getName() + "--- " +parameter.getName());
                    }
                    System.out.println(stringBuilder);
                }
            }
            System.out.println("R  "+r);
        }
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }
}
